package com.rockwell.sniffyhunter;

import java.util.Map;
import java.util.HashMap;

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.os.Bundle;
import android.preference.EditTextPreference;
import android.preference.Preference;
import android.preference.PreferenceActivity;
import android.preference.PreferenceCategory;
import android.preference.PreferenceManager;
import org.opencv.core.Scalar;

import com.rockwell.sniffyhunter.R;
import com.rockwell.sniffyhunter.model.MazePath;
import com.rockwell.sniffyhunter.model.MotorProfile;
import com.rockwell.sniffyhunter.model.MazePath.MazeNo;
import com.rockwell.sniffyhunter.utils.DetectionIndex;

/**
 * A {@link PreferenceActivity} that presents a set of application settings. On
 * handset devices, settings are presented as a single list. On tablets,
 * settings are split by category, with category headers shown to the left of
 * the list of settings.
 * <p>
 * See <a href="http://developer.android.com/design/patterns/settings.html">
 * Android Design: Settings</a> for design guidelines and the <a
 * href="http://developer.android.com/guide/topics/ui/settings.html">Settings
 * API Guide</a> for more information on developing a Settings UI.
 */
@SuppressLint("UseSparseArrays") 
public class SettingsActivity extends PreferenceActivity implements OnSharedPreferenceChangeListener {
	private static final String KEY_ROBOT_WIDTH = "robot_width";
	private static final String KEY_ROBOT_LENGTH = "robot_length";
	
	private static final String KEY_ROBOT_START_ZONE = "robot_start_zone";
	
	private static final String KEY_MAZE_WIDTH = "maze_width";
	private static final String KEY_MAZE_HEIGHT = "maze_height";
	private static final String KEY_MAX_STEPS = "max_steps";
	
	@SuppressWarnings("serial")
	private static final Map<Integer, String>  KEY_DETECTION_COLOR_H = new HashMap<Integer, String>() {
		{
			put(DetectionIndex.TREASURE, "treasure_color_h");
			put(DetectionIndex.OBSTACLE, "obstacle_color_h");
			put(DetectionIndex.MAZE1, "maze1_color_h");
			put(DetectionIndex.MAZE2, "maze2_color_h");
			put(DetectionIndex.MAZE3, "maze3_color_h");
			put(DetectionIndex.DROPZONE, "dropzone_color_h");
			put(DetectionIndex.MAZE_EXIT, "mazeexit_color_h");
		}
	};
	@SuppressWarnings("serial")
	private static final Map<Integer, String>  KEY_DETECTION_COLOR_S = new HashMap<Integer, String>() {
		{
			put(DetectionIndex.TREASURE, "treasure_color_s");
			put(DetectionIndex.OBSTACLE, "obstacle_color_s");
			put(DetectionIndex.MAZE1, "maze1_color_s");
			put(DetectionIndex.MAZE2, "maze2_color_sh");
			put(DetectionIndex.MAZE3, "maze3_color_s");
			put(DetectionIndex.DROPZONE, "dropzone_color_s");
			put(DetectionIndex.MAZE_EXIT, "mazeexit_color_s");
		}
	};
	@SuppressWarnings("serial")
	private static final Map<Integer, String>  KEY_DETECTION_COLOR_V = new HashMap<Integer, String>() {
		{
			put(DetectionIndex.TREASURE, "treasure_color_v");
			put(DetectionIndex.OBSTACLE, "obstacle_color_v");
			put(DetectionIndex.MAZE1, "maze1_color_v");
			put(DetectionIndex.MAZE2, "maze2_color_v");
			put(DetectionIndex.MAZE3, "maze3_color_v");
			put(DetectionIndex.DROPZONE, "dropzone_color_v");
			put(DetectionIndex.MAZE_EXIT, "mazeexit_color_v");
		}
	};
	
	private static final String KEY_PROFILE1_LEFT_MOTOR = "left_motor1";
	private static final String KEY_PROFILE1_RIGHT_MOTOR = "right_motor1";
	
	private static final String KEY_PROFILE2_LEFT_MOTOR = "left_motor2";
	private static final String KEY_PROFILE2_RIGHT_MOTOR = "right_motor2";
	
	private static final String KEY_PROFILE3_LEFT_MOTOR = "left_motor3";
	private static final String KEY_PROFILE3_RIGHT_MOTOR = "right_motor3";
	
	private static final String KEY_PROFILE4_LEFT_MOTOR = "left_motor4";
	private static final String KEY_PROFILE4_RIGHT_MOTOR = "right_motor4";
	
	private static final String KEY_PROFILE5_LEFT_MOTOR = "left_motor5";
	private static final String KEY_PROFILE5_RIGHT_MOTOR = "right_motor5";
	
	private static final String KEY_PROFILE6_LEFT_MOTOR = "left_motor6";
	private static final String KEY_PROFILE6_RIGHT_MOTOR = "right_motor6";

	private static final String[] s_profile_left_motor = {
		KEY_PROFILE1_LEFT_MOTOR,
		KEY_PROFILE2_LEFT_MOTOR,
		KEY_PROFILE3_LEFT_MOTOR,
		KEY_PROFILE4_LEFT_MOTOR,
		KEY_PROFILE5_LEFT_MOTOR,
		KEY_PROFILE6_LEFT_MOTOR
	};
	
	private static final String[] s_profile_right_motor = {
		KEY_PROFILE1_RIGHT_MOTOR,
		KEY_PROFILE2_RIGHT_MOTOR,
		KEY_PROFILE3_RIGHT_MOTOR,
		KEY_PROFILE4_RIGHT_MOTOR,
		KEY_PROFILE5_RIGHT_MOTOR,
		KEY_PROFILE6_RIGHT_MOTOR
	};
	

	private static final String KEY_PREDEFINED_PATH_ENTRANCE = "predefined_path_entrance";
	private static final String KEY_PREDEFINED_PATH_EASY = "predefined_path_easy";
	private static final String KEY_PREDEFINED_PATH_MEDIUM = "predefined_path_medium";
	private static final String KEY_PREDEFINED_PATH_HARD = "predefined_path_hard";
	
	private static final String KEY_USE_PREDEFINED_PATH = "use_predefined_path";
	private static final String KEY_PREDEFINED_TYPE = "predefined_type";
	
	private static final String KEY_USE_STEP_MODE = "step_mode";
	private static final String KEY_LEFT_FIRST = "left_first";
	private static final String KEY_USE_COMPASS_COMPENSATION = "compass_compensation";
	
	private static final String KEY_INITIAL_X = "initial_x";
	private static final String KEY_INITIAL_Y = "initial_y";
	private static final String KEY_INITIAL_DIR = "initial_dir";
	private static final String KEY_INITIAL_MAZENO = "initial_mazeno";
	
	@Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
 
        addPreferencesFromResource(R.xml.settings);
 
        for (int i = 0; i < getPreferenceScreen().getPreferenceCount(); i++) {
            initSummary(getPreferenceScreen().getPreference(i));
        }
    }
	
    /**
     * Populate the activity with the top-level headers.
     */
    //@Override
    //public void onBuildHeaders(List<Header> target) {
    //    loadHeadersFromResource(R.xml.pref_headers, target);
    //}
    
    @Override
    protected void onResume() {
        super.onResume();
        // Set up a listener whenever a key changes
        SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(this);
        pref.registerOnSharedPreferenceChangeListener(this);
    }

    @Override
    protected void onPause() {
        super.onPause();
        // Unregister the listener whenever a key changes
        SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(this);
        pref.unregisterOnSharedPreferenceChangeListener(this);
    }

	@Override
	public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
		updatePrefSummary(findPreference(key));
	}
	
    private static void initSummary(Preference p) {
        if (p instanceof PreferenceCategory) {
            PreferenceCategory pCat = (PreferenceCategory) p;
            for (int i = 0; i < pCat.getPreferenceCount(); i++) {
                initSummary(pCat.getPreference(i));
            }
        } else {
            updatePrefSummary(p);
        }
    }

	private static void updatePrefSummary(Preference p) {
		if (p instanceof EditTextPreference) {
			EditTextPreference pref = (EditTextPreference)p;
			p.setSummary(pref.getText());
		}
	}
	
	public static int getRobotWidth(Context context) {
		String str = PreferenceManager.getDefaultSharedPreferences(context)
				.getString(KEY_ROBOT_WIDTH, "15");
		return Integer.parseInt(str);
	}
	
	public static int getRobotLength(Context context) {
		String str = PreferenceManager.getDefaultSharedPreferences(context)
				.getString(KEY_ROBOT_LENGTH, "15");
		return Integer.parseInt(str);
	}
	
	public static int getRobotStartZone(Context context) {
		String str = PreferenceManager.getDefaultSharedPreferences(context)
				.getString(KEY_ROBOT_START_ZONE, "1");
		return Integer.parseInt(str);
	}
	
	public static Scalar deserializeDetectionColor(Context context, int detectionIndex) {
		SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(context);
		
		Scalar detectionColor = new Scalar(255);
		String h = sharedPrefs.getString(KEY_DETECTION_COLOR_H.get(detectionIndex), "255");
		String s = sharedPrefs.getString(KEY_DETECTION_COLOR_S.get(detectionIndex), "0");
		String v = sharedPrefs.getString(KEY_DETECTION_COLOR_V.get(detectionIndex), "0");
		detectionColor.val[0] = Float.parseFloat(h);
		detectionColor.val[1] = Float.parseFloat(s);
		detectionColor.val[2] = Float.parseFloat(v);
		
		return detectionColor;
	}
	
	public static void serializeDetectionColor(Context context, Scalar detectionColor, int detectionIndex) {
		SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(context);
		
		Editor editor = sharedPrefs.edit();
        editor.putString(KEY_DETECTION_COLOR_H.get(detectionIndex), String.valueOf(detectionColor.val[0]));
        editor.putString(KEY_DETECTION_COLOR_S.get(detectionIndex), String.valueOf(detectionColor.val[1]));
        editor.putString(KEY_DETECTION_COLOR_V.get(detectionIndex), String.valueOf(detectionColor.val[2]));
        editor.commit();
	}

	public static MotorProfile getMotorProfile(Context context, int index) {
		String strLeft = PreferenceManager.getDefaultSharedPreferences(context)
				.getString(s_profile_left_motor[index], "10");

		String strRight = PreferenceManager.getDefaultSharedPreferences(context)
				.getString(s_profile_right_motor[index], "10");
		
		return new MotorProfile(Integer.parseInt(strLeft), Integer.parseInt(strRight));
	}
	
	public static void setPredefinedPath(Context context, String path, MazePath.MazeNo mazeNo) {
		SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(context);
		Editor editor = sharedPrefs.edit();
		if (mazeNo == MazePath.MazeNo.Entrance)
		{
			editor.putString(KEY_PREDEFINED_PATH_ENTRANCE, path);
		}
		else if (mazeNo == MazePath.MazeNo.Easy)
		{
			editor.putString(KEY_PREDEFINED_PATH_EASY, path);
		}
		else if (mazeNo == MazePath.MazeNo.Medium)
		{
			editor.putString(KEY_PREDEFINED_PATH_MEDIUM, path);
		}
		else if (mazeNo == MazePath.MazeNo.Hard)
		{
			editor.putString(KEY_PREDEFINED_PATH_HARD, path);
		}
		
        editor.commit();
	}
	
	public static String getPredefinedPath(Context context, MazePath.MazeNo mazeNo) {
		String path = "";
	
		if (mazeNo == MazePath.MazeNo.Entrance)
		{
		    path = PreferenceManager.getDefaultSharedPreferences(context)
				.getString(KEY_PREDEFINED_PATH_ENTRANCE, "");
		} 
		else if (mazeNo == MazePath.MazeNo.Easy)
		{
		    path = PreferenceManager.getDefaultSharedPreferences(context)
				.getString(KEY_PREDEFINED_PATH_EASY, "");
		}
		else if (mazeNo == MazePath.MazeNo.Medium)
		{
		    path = PreferenceManager.getDefaultSharedPreferences(context)
				.getString(KEY_PREDEFINED_PATH_MEDIUM, "");
		}
		else if (mazeNo == MazePath.MazeNo.Hard)
		{
		    path = PreferenceManager.getDefaultSharedPreferences(context)
				.getString(KEY_PREDEFINED_PATH_HARD, "");
		}
		
		return path;
	}
	
	public static String getPredefinedPath(Context context) {
		String path = "";
		String mazeNo = PreferenceManager.getDefaultSharedPreferences(context).getString(KEY_PREDEFINED_TYPE, "Hard");
	
		if (mazeNo == MazePath.MazeNo.Entrance.toString())
		{
		    path = PreferenceManager.getDefaultSharedPreferences(context)
				.getString(KEY_PREDEFINED_PATH_ENTRANCE, "");
		} 
		else if (mazeNo == MazePath.MazeNo.Easy.toString())
		{
		    path = PreferenceManager.getDefaultSharedPreferences(context)
				.getString(KEY_PREDEFINED_PATH_EASY, "");
		}
		else if (mazeNo == MazePath.MazeNo.Medium.toString())
		{
		    path = PreferenceManager.getDefaultSharedPreferences(context)
				.getString(KEY_PREDEFINED_PATH_MEDIUM, "");
		}
		else if (mazeNo == MazePath.MazeNo.Hard.toString())
		{
		    path = PreferenceManager.getDefaultSharedPreferences(context)
				.getString(KEY_PREDEFINED_PATH_HARD, "");
		}
		
		return path;
	}
	
	
	public static boolean hasPredefinedPath(Context context) {
		String path = "";
		path = getPredefinedPath(context);
		
		if (path == "")
			return false;
		else
			return true;				
	}
	
	public static void usePredefinedPath(Context context, boolean use) {
		SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(context);
		Editor editor = sharedPrefs.edit();
        editor.putBoolean(KEY_USE_PREDEFINED_PATH, use);
        editor.commit();
	}
	
	public static boolean usePredefinedPath(Context context) {
		return PreferenceManager.getDefaultSharedPreferences(context)
				.getBoolean(KEY_USE_PREDEFINED_PATH, false);
	}

	public static void useStepMode(Context context, boolean use) {
		SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(context);
		Editor editor = sharedPrefs.edit();
        editor.putBoolean(KEY_USE_STEP_MODE, use);
        editor.commit();
	}
	
	public static boolean leftFirst(Context context) {
		return PreferenceManager.getDefaultSharedPreferences(context)
				.getBoolean(KEY_LEFT_FIRST, false);
	}
	
	public static void useCompassCompensation(Context context, boolean use) {
		SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(context);
		Editor editor = sharedPrefs.edit();
        editor.putBoolean(KEY_USE_COMPASS_COMPENSATION, use);
        editor.commit();
	}
	
	public static boolean useStepMode(Context context) {
		return PreferenceManager.getDefaultSharedPreferences(context)
				.getBoolean(KEY_USE_STEP_MODE, true);
	}
	
	public static boolean useCompassCompensation(Context context) {
		return PreferenceManager.getDefaultSharedPreferences(context)
				.getBoolean(KEY_USE_COMPASS_COMPENSATION, false);
	}

	public static int getMazeWidth(Context context) {
		String width = PreferenceManager.getDefaultSharedPreferences(context)
				.getString(KEY_MAZE_WIDTH, "16");
		
		return Integer.parseInt(width);
	}
	
	public static int getMazeHeight(Context context) {
		String height = PreferenceManager.getDefaultSharedPreferences(context)
				.getString(KEY_MAZE_HEIGHT, "16");
		
		return Integer.parseInt(height);
	}
	
	public static int getMaximumSteps(Context context) {
		String steps = PreferenceManager.getDefaultSharedPreferences(context)
				.getString(KEY_MAX_STEPS, "60");
		
		return Integer.parseInt(steps);
	}
	
	public static void setInitialX(Context context, int x) {
		SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(context);
		Editor editor = sharedPrefs.edit();
        editor.putInt(KEY_INITIAL_X, x);
        editor.commit();
	}
	
	public static int getInitialX(Context context) {
		int x = PreferenceManager.getDefaultSharedPreferences(context)
				.getInt(KEY_INITIAL_X, 15);
		
		return x;
	}
	
	public static void setInitialY(Context context, int y) {
		SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(context);
		Editor editor = sharedPrefs.edit();
        editor.putInt(KEY_INITIAL_Y, y);
        editor.commit();
	}
	
	public static int getInitialY(Context context) {
		int y = PreferenceManager.getDefaultSharedPreferences(context)
				.getInt(KEY_INITIAL_Y, 15);
		
		return y;
	}
	
	
	public static void setInitialDir(Context context, MazePath.Direction dir) {
		SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(context);
		Editor editor = sharedPrefs.edit();
        editor.putInt(KEY_INITIAL_DIR, dir.ordinal());
        editor.commit();
	}
	
	public static MazePath.Direction getInitialDir(Context context) {
		int ordinal = PreferenceManager.getDefaultSharedPreferences(context)
				.getInt(KEY_INITIAL_DIR, 0);
		
		return MazePath.Direction.values()[ordinal];
	}
	
	public static void setInitialMazeNo(Context context, MazePath.MazeNo mazeNo) {
		SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(context);
		Editor editor = sharedPrefs.edit();
        editor.putInt(KEY_INITIAL_MAZENO, mazeNo.ordinal());
        editor.commit();
	}
	
	public static void getInitialMazeNo(Context context, MazePath.Direction dir) {
		SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(context);
		Editor editor = sharedPrefs.edit();
        editor.putInt(KEY_INITIAL_MAZENO, dir.ordinal());
        editor.commit();
	}
	
	public static MazePath.Direction getInitialMazeNo(Context context) {
		int ordinal = PreferenceManager.getDefaultSharedPreferences(context)
				.getInt(KEY_INITIAL_MAZENO, 0);
		
		return MazePath.Direction.values()[ordinal];
	}
	
	private static final String JUNCTION_INDEX_DISTANCE = "junction_index_distance";
	private static final String JUNCTION_LEFT_MOVEBACK_DISTANCE = "turn_left_moveback_distance";
	private static final String JUNCTION_RIGHT_MOVEBACK_DISTANCE = "turn_right_moveback_distance";
	private static final String JUNCTION_UTURN_MOVEBACK_INDEX = "uturn_moveback_index";
	
	public static int getJunctionIndexDistance(Context context) {
		String ordinal = PreferenceManager.getDefaultSharedPreferences(context)
				.getString(JUNCTION_INDEX_DISTANCE, "20");
		return Integer.parseInt(ordinal);
	}
	
	public static void setJunctionIndexDistance(Context context, int distance) {
		SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(context);
		
		Editor editor = sharedPrefs.edit();
        editor.putString(JUNCTION_INDEX_DISTANCE, String.valueOf(distance));
        editor.commit();
	}
	
	public static int getLeftJunctionMovebackDistance(Context context) {
		String ordinal = PreferenceManager.getDefaultSharedPreferences(context)
				.getString(JUNCTION_LEFT_MOVEBACK_DISTANCE, "70");
		return Integer.parseInt(ordinal);
	}
	
	public static void setLeftJunctionMovebackDistance(Context context, int distance) {
		SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(context);
		
		Editor editor = sharedPrefs.edit();
        editor.putString(JUNCTION_LEFT_MOVEBACK_DISTANCE, String.valueOf(distance));
        editor.commit();
	}
	
	public static int getRightJunctionMovebackDistance(Context context) {
		String ordinal = PreferenceManager.getDefaultSharedPreferences(context)
				.getString(JUNCTION_RIGHT_MOVEBACK_DISTANCE, "50");
		return Integer.parseInt(ordinal);
	}
	
	public static void setRightJunctionMovebackDistance(Context context, int distance) {
		SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(context);
		
		Editor editor = sharedPrefs.edit();
        editor.putString(JUNCTION_RIGHT_MOVEBACK_DISTANCE, String.valueOf(distance));
        editor.commit();
	}
	
	public static int getUTurnMovebackDistance(Context context) {
		String ordinal = PreferenceManager.getDefaultSharedPreferences(context)
				.getString(JUNCTION_UTURN_MOVEBACK_INDEX, "30");
		return Integer.parseInt(ordinal);
	}
	
	public static void setUTurnMovebackIndex(Context context, int distance) {
		SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(context);
		
		Editor editor = sharedPrefs.edit();
        editor.putString(JUNCTION_UTURN_MOVEBACK_INDEX, String.valueOf(distance));
        editor.commit();
	}
}
